CREATE PROCEDURE SP_AUTORIZAR_DESPACHO_VALE 
(
  CODEDESPACHO IN VARCHAR2  
, CODETARJETA IN VARCHAR2  
, CANTIDAD IN NUMBER  
, CARA IN VARCHAR2  
, ISLA IN VARCHAR2  
, CODEUSUARIO IN VARCHAR2  
, CODEESTACION IN VARCHAR2
, INDICADOR OUT VARCHAR2  --- debe ser 0 (cero) cuando hubo error, y 1 (uno) cuando fue un exito la operacion
, MENSAJEERROR OUT VARCHAR2 --- mensaje de indicacion de cual fue el error, si es que lo hubo
) AS

err_num number;
err_msg varchar2(255);
conteotabla number;
saldovale number;
idclientepersona number;
idsolicdespachovale number;
cantidadrestante number;

BEGIN
  
  indicador     :=  '1';
  mensajeerror  :=  'No Hubo Errores';
  idsolicdespachovale := 0;
  cantidadrestante := 0;
  conteotabla := 0;
  saldovale := 0;
  idclientepersona := -1;
  
  select count(*) into conteotabla
      from clpb_tarjeta_persona where co_codigo_tarjeta_persona = codetarjeta
      and st_tarjeta_persona = 'Y';
      if(conteotabla = 0) then
        indicador    := '0';
        mensajeerror := 'Tarjeta invalida.';
      end if;
      
      if(conteotabla > 0) then
        conteotabla := 0;
        select count(*) into conteotabla 
        from clpb_tarjeta_persona where co_codigo_tarjeta_persona = codetarjeta
        and da_fecha_anulacion is null;
        if(conteotabla = 0) then
          indicador    := '0';
          mensajeerror :=  'Tarjeta anulada.';
        end if;
      end if;
      
      if(conteotabla > 0) then
        conteotabla := 0;
        select count(*) into conteotabla
        from clpb_tarjeta_persona where co_codigo_tarjeta_persona = codetarjeta
        and da_fecha_inicio_vigencia <= sysdate;
        if(conteotabla = 0) then
          indicador    := '0';
          mensajeerror :=  'Vigencia de la tarjeta no valida.';
        end if;
      end if;
      
      if(conteotabla > 0) then
        conteotabla := 0;
        select count(*) into conteotabla 
        from clpb_tarjeta_persona tp
        join clpb_cliente_persona cp on tp.co_cliente_persona = cp.id 
        where tp.co_codigo_tarjeta_persona = codetarjeta
        and cp.st_cliente_persona = 'Y' 
        and cp.st_habilitado = 'Y';        
        if(conteotabla = 0) then
          indicador    := '0';
          mensajeerror :=  'Tarjeta no asignada a un cliente habilitado.';
        end if;
      end if;     

      if(conteotabla > 0) then
        conteotabla := 0;
        select count(cp.id), cp.id into conteotabla, idclientepersona
        from clpb_tarjeta_persona tp
        join clpb_cliente_persona cp on tp.co_cliente_persona = cp.id 
        where tp.co_codigo_tarjeta_persona = codetarjeta
        and cp.da_fecha_inscripcion is not null
        and cp.da_fecha_inscripcion <= sysdate
        and cp.st_cliente_persona = 'Y' 
        and cp.st_habilitado = 'Y' 
        group by cp.id;
        
        if(conteotabla = 0) then
          indicador    := '0';
          mensajeerror :=  'Cliente no afiliado a CLUBPGN.';
        end if;
      end if;
      
      if(conteotabla > 0) then
        conteotabla := 0;
        select count(*) into conteotabla
        from clpb_estacion where co_codigo_cofide = codeestacion
        and st_estacion = 'Y';
        if(conteotabla = 0) then
          indicador    := '0';
          mensajeerror :=  'Codigo de estacion invalido.';
        end if;
      end if;
      
      if(conteotabla > 0) then        
        if(cantidad = 0) then
          conteotabla  :=  0;
          indicador    := '0';
          mensajeerror := 'Se debe indicar el valor del premio vale.';
        end if;
      end if;
      
      if(conteotabla > 0) then
        conteotabla  :=  0;
        select count(*) into conteotabla from clpm_vale_cliente_persona
        where co_cliente_persona = idclientepersona and da_fecha_vencimiento >= sysdate 
        and va_saldo > 0 and st_vale_cliente_persona = 'Y';
        
        if(conteotabla = 0) then
          indicador    := '0';
          mensajeerror :=  'El cliente no cuenta con premios vales, no puede realizar la operacion.';
        end if;      
      end if;
      
      if(conteotabla > 0) then
        select sum(va_saldo) into saldovale from clpm_vale_cliente_persona
        where co_cliente_persona = idclientepersona and da_fecha_vencimiento >= sysdate 
        and va_saldo > 0 and st_vale_cliente_persona = 'Y';
        
        if(saldovale < cantidad) then
          conteotabla  :=  0;
          indicador    := '0';
          mensajeerror :=  'El cliente no cuenta con saldo suficiente para la cantidad solicitada.';
        end if;      
      end if;
      
      if(conteotabla > 0) then
        
        select seq_solic_despacho_vale.nextval into
        idsolicdespachovale from dual;
        
        insert into clpm_solicitud_despacho_vale(
          id, co_code_despacho, co_code_tarjeta, va_cantidad_solicitada, co_code_cara,
          co_code_isla, co_code_usuario, co_code_estacion, st_proceso_ok, de_mensaje, st_confirmado_proceso,
          st_confirmado_regularizacion, va_cantidad_despachada, co_cliente_persona, co_usuario_creador,
          da_fecha_creacion, co_usuario_modificador, da_fecha_modificacion, st_solicitud_despacho_vale
        )values(
          idsolicdespachovale, codedespacho, codetarjeta, cantidad, cara, isla,
          codeusuario, codeestacion, indicador, mensajeerror, 'N', 'N', cantidad, idclientepersona, 
          'clubpgn', sysdate, null, null, 'Y');   
          
          
          cantidadrestante := cantidad;
          
          -- verificando los vales a usar desde los mas antiguos
          for bnvale in (select va_saldo, id from clpm_vale_cliente_persona
            where co_cliente_persona = idclientepersona and da_fecha_vencimiento >= sysdate 
            and va_saldo > 0 and st_vale_cliente_persona = 'Y'
            order by id asc)
          
          loop
                      
            if(cantidadrestante >= bnvale.va_saldo) then            
              
              update clpm_vale_cliente_persona
                set va_saldo = 0,
                    co_usuario_modificador = 'clubpgn',
                    da_fecha_modificacion = sysdate
              where id = bnvale.id;              
              cantidadrestante := cantidadrestante - bnvale.va_saldo;
              
              insert into clpr_vale_solicitud_despacho(
                id, co_vale_cliente_persona, co_solicitud_despacho_vale, co_usuario_creador,
                da_fecha_creacion, co_usuario_modificador, da_fecha_modificacion, st_vale_solicitud_despacho
              ) values (
                SEQ_VALE_SOL_DESPACHO.NEXTVAL, bnvale.id, idsolicdespachovale, 'clubpgn', sysdate, 
                null, null, 'Y');
                            
            else
            
              update clpm_vale_cliente_persona
                set va_saldo = va_saldo - cantidadrestante,
                    co_usuario_modificador = 'clubpgn',
                    da_fecha_modificacion = sysdate
              where id = bnvale.id;              
              cantidadrestante := 0; 
              
              insert into clpr_vale_solicitud_despacho(
                id, co_vale_cliente_persona, co_solicitud_despacho_vale, co_usuario_creador,
                da_fecha_creacion, co_usuario_modificador, da_fecha_modificacion, st_vale_solicitud_despacho
              ) values (
                seq_vale_sol_despacho.nextval, bnvale.id, idsolicdespachovale, 'clubpgn', sysdate, 
                null, null, 'Y');
              
            end if;
            
            EXIT WHEN cantidadrestante = 0;          
          end loop;
     
      ELSE
      
        if(idclientepersona = -1) then 
          idclientepersona := null;
        end if;
        
        insert into clpm_solicitud_despacho_vale(
          id, co_code_despacho, co_code_tarjeta, va_cantidad_solicitada, co_code_cara,
          co_code_isla, co_code_usuario, co_code_estacion, st_proceso_ok, de_mensaje, st_confirmado_proceso,
          st_confirmado_regularizacion, va_cantidad_despachada, co_cliente_persona, co_usuario_creador,
          da_fecha_creacion, co_usuario_modificador, da_fecha_modificacion, st_solicitud_despacho_vale
        )values(
          seq_solic_despacho_vale.nextval, codedespacho, codetarjeta, cantidad, cara, isla,
          codeusuario, codeestacion, indicador, mensajeerror, 'N', 'N', cantidad, idclientepersona, 
          'clubpgn', sysdate, null, null, 'Y');
        
      end if;
      
      commit;
  
exception
  when others then
    dbms_output.put_line('HAY ALGUN ERROR EN EL STORE NO PREVISTO');
    err_num := sqlcode;
    err_msg := sqlerrm;
    dbms_output.put_line('Error:'||to_char(err_num));
    dbms_output.put_line(err_msg);
    indicador       := '0';
    mensajeerror    := 'Error:'||err_num||' ' ||err_msg;
    rollback;
  
END SP_AUTORIZAR_DESPACHO_VALE;